using Inaction;
using Inaction.ServiceContract;
using Inaction.Core;
using Inaction.Mapping;
using Inaction.Util;
using System;
using System.Linq;
using System.Security.Principal;

namespace Inaction.ServiceProxy
{
    public class LocalProxy : IProxy
    {
        public LocalProxy() { }

        #region
        public void Login()
        {
            if (Inaction.Security.Principal.Instance == null)
            {
                throw new Exception(Inaction.Resource.Properties.Resources.PrincipalInstanceNotConfiged);
            }
            Inaction.Security.Principal.Instance =ServiceContainer.GetService<ISecurityProvider>().Login();
        }
        public object Query(Type type, SqlStatement sql)
        {
            CheckIdentity();
            ClassInfo info = null;
            if (type.GetInterface(typeof(IEntityList).FullName) != null)
            {
                var entityType = type.BaseType;
                while (!entityType.IsGenericType)
                    entityType = entityType.BaseType;
                entityType = entityType.GenericTypeArguments.FirstOrDefault(p => p.IsSubclassOf(typeof(ModelBase)));
                info = Inaction.Mapping.ClassInfo.LoadInfo(entityType);
            }
            else
            {
                info = Inaction.Mapping.ClassInfo.LoadInfo(type);
            }

            var method = TypeHelper.GetStaticMethodInfo(type, "DoQuery", new Type[1] { typeof(SqlStatement) });
            var datas = method.Invoke(null, new object[] { sql });
            return datas;
        }
        public ISavable Save(ISavable obj)
        {
            CheckIdentity();
            obj.DoSave();
            var type = obj.GetType();
            ClassInfo info = null;
            if (type.GetInterface(typeof(IEntityList).FullName) != null)
            {
                var entityType = type.BaseType;
                while (!entityType.IsGenericType)
                    entityType = entityType.BaseType;
                entityType = entityType.GenericTypeArguments.FirstOrDefault(p => p.IsSubclassOf(typeof(ModelBase)));
                info = Inaction.Mapping.ClassInfo.LoadInfo(entityType);
            }
            else
            {
                info = Inaction.Mapping.ClassInfo.LoadInfo(type);
            }
            return obj;
        }
        public SqlCommand Excute(SqlCommand command)
        {
            CheckIdentity();
            command.Execute();
            return command;
        }
        public RemotingMethod Invoke(RemotingMethod method)
        {
            CheckIdentity();
            method.DoInvoke();
            return method;
        }

        public void CheckIdentity()
        {
            ServiceContainer.GetService<ISecurityProvider>().CheckIdentity();
        }
        #endregion

        void IProxy.Login()
        {
            this.Login();
        }

        object IProxy.Save(ISavable obj)
        {
            return this.Save(obj);
        }

        object IProxy.Excute(SqlCommand command)
        {
            return this.Excute(command);
        }

        object IProxy.Invoke(RemotingMethod method)
        {
            return this.Invoke(method);
        }
    }
}